{ "cells": [ { "cell_type": "markdown", "id": "specific-boulder", "metadata": {}, "source": [ "# Producción de jugos - Solución" ] }, { "cell_type": "markdown", "id": "written-elephant", "metadata": {}, "source": [ "Tags: Mezcla, Recurso" ] }, { "cell_type": "code", "execution_count": 1, "id": "fe8c0d77", "metadata": { "tags": [ "hide-input", "thebe-init" ] }, "outputs": [], "source": [ "import os\n", "# Por precaución, cambiamos el directorio activo de Python a aquel que contenga este notebook\n", "if \"optimizacion\" in os.listdir():\n", " os.chdir(r\"optimizacion/Formulaciones/3. Produccion de jugos/\")" ] }, { "cell_type": "markdown", "id": "annoying-circus", "metadata": {}, "source": [ "## Enunciado\n", "\n", "" ] }, { "cell_type": "markdown", "id": "d32abf6a", "metadata": {}, "source": [ "OptiJuice es una empresa que produce jugos. Ellos han decidido producir un nuevo conjunto de jugos autóctonos ($K$). Los jugos son una mezcla de diferentes frutas tropicales ($R$) dentro de las que se encuentran la piña, la guayaba, el níspero y el zapote. Cada uno de los tipos de jugo se diferencia de los demás en la cantidad de litros de zumo que tiene de las distintas frutas. Es por esto que, para garantizar la calidad de los jugos es necesario que el jugo del tipo $k \\in K$ contenga entre un $l_{ki}$% y un $u_{ki}$% de litros de zumo de la fruta $i \\in R$. Para la producción de jugos, OptiJuice tiene disponibles $b_i$ litros de zumo de la fruta $i \\in R$. La compañía espera una demanda mínima de $d_k$ litros y desea vender cada litro de jugo del tipo $k \\in K$ a $p_k$ pesos. La información mencionada se presenta en las Tablas 1 a 4." ] }, { "cell_type": "markdown", "id": "f29e2b10", "metadata": {}, "source": [ "

Tabla 1. Mínimo porcentaje de las frutas en los jugos

" ] }, { "cell_type": "markdown", "id": "5d0a9e80", "metadata": {}, "source": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Mínimo porcentajeFrutas
JugosPiña (%)Guayaba (%)Nispero (%)Zapote (%)
Saludable32271213
Tropical18202111
Mañanero7312822
Colombiano1151518
Refrescante1629223
Light26191430
" ] }, { "cell_type": "markdown", "id": "cd0e2fa8", "metadata": {}, "source": [ "

Tabla 2. Máximo porcentaje de las frutas en los jugos

" ] }, { "cell_type": "markdown", "id": "bf20ec8f", "metadata": {}, "source": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Máximo porcentajeFrutas
JugosPiña (%)Guayaba (%)Nispero (%)Zapote (%)
Saludable95836687
Tropical92766956
Mañanero81617894
Colombiano82886398
Refrescante60857378
Light50558291
" ] }, { "cell_type": "markdown", "id": "b54ba336", "metadata": {}, "source": [ "

Tabla 3. Litros disponibles de cada fruta

" ] }, { "cell_type": "markdown", "id": "72aa62c6", "metadata": {}, "source": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
FrutasLitros disponibles
Piña6,318
Guayaba4,500
Nispero4,683
Zapote2,121
" ] }, { "cell_type": "markdown", "id": "5e2f9bf8", "metadata": {}, "source": [ "

Tabla 4. Demanda mínima y precio de cada jugo

" ] }, { "cell_type": "markdown", "id": "7609baaa", "metadata": {}, "source": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
JugosDemanda mínimaPrecio
Saludable1,2009,000
Tropical9255,000
Mañanero1,8656,000
Colombiano1,03510,000
Refrescante2,2317,000
Light1,3538,000
" ] }, { "cell_type": "markdown", "id": "40165ecf", "metadata": {}, "source": [ "Formula un programa lineal que le permita OptiJuice responder la siguiente pregunta: ¿Cuántos litros de zumo de cada fruta se deben mezclar para producir cada uno de los tipos de jugos, de manera que se cumplan las condiciones previamente expuestas y se maximicen los ingresos totales?" ] }, { "cell_type": "markdown", "id": "linear-shadow", "metadata": {}, "source": [ "## Formulación\n", "\n", "" ] }, { "cell_type": "markdown", "id": "f08dc1b9", "metadata": {}, "source": [ "**a.** Formula matemáticamente un modelo de optimización de forma general que represente la\n", "situación anterior. Defina clara y rigurosamente: \n", "- Conjuntos\n", "- Parámetros\n", "- Variables de decisión\n", "- Restricciones\n", "- Naturaleza de las variables\n", "- Función objetivo" ] }, { "cell_type": "markdown", "id": "6af5479a", "metadata": {}, "source": [ "### Conjuntos" ] }, { "cell_type": "markdown", "id": "bde43045", "metadata": {}, "source": [ "- $K$: conjunto de jugos autóctonos\n", "- $R$: conjunto de frutas tropicales" ] }, { "cell_type": "markdown", "id": "c475ff6e", "metadata": {}, "source": [ "### Parámetros" ] }, { "cell_type": "markdown", "id": "f4a5e4a2", "metadata": {}, "source": [ "- $l_{ki}$%: porcentaje mínimo de litros de zumo de la fruta $i\\in R$ que debe tener el jugo del tipo $k\\in K$\n", "- $u_{ki}$%: porcentaje máximo de litros de zumo de la fruta $i\\in R$ que debe tener el jugo del tipo $k\\in K$\n", "- $b_i$: litros de zumo de la fruta $i\\in R$ disponibles\n", "- $d_k$: demanda mínima (en litros) del jugo de tipo $k\\in K$ \n", "- $p_k$: precio de un litro del jugo de tipo $k\\in K$" ] }, { "cell_type": "markdown", "id": "loaded-equipment", "metadata": {}, "source": [ "### Variables de decisión" ] }, { "cell_type": "markdown", "id": "ae653995", "metadata": {}, "source": [ "- $x_{ki}$: cantidad (en litros) del zumo de la fruta $i\\in R$ destinados a la producción del jugo de tipo $k\\in K$" ] }, { "cell_type": "markdown", "id": "north-language", "metadata": {}, "source": [ "### Restricciones" ] }, { "cell_type": "markdown", "id": "f2496fcf", "metadata": {}, "source": [ "El jugo del tipo $k\\in K$ debe contener entre un $l_{ki}$% y un $u_{ki}$% de zumo de la fruta $i\\in R$:" ] }, { "cell_type": "markdown", "id": "6caf730f", "metadata": {}, "source": [ "$$\n", " x_{ki} \\ge l_{ki}\\%\\sum_{j\\in R} x_{kj},\\ \\forall k\\in K,i\\in R;\n", "$$" ] }, { "cell_type": "markdown", "id": "c8564f67", "metadata": {}, "source": [ "$$\n", " x_{ki} \\le u_{ki}\\%\\sum_{j\\in R} x_{kj},\\ \\forall k\\in K, i\\in R;\n", "$$" ] }, { "cell_type": "markdown", "id": "4c86b6a1", "metadata": {}, "source": [ "OptiJuice puede utilizar máximo $b_i$ litros de zumo de la fruta $i\\in R$:" ] }, { "cell_type": "markdown", "id": "43f3f0d4", "metadata": {}, "source": [ "$$\n", " \\sum_{k\\in K} x_{ki} \\le b_i,\\ \\forall i\\in R;\n", "$$" ] }, { "cell_type": "markdown", "id": "268aeaf2", "metadata": {}, "source": [ "OptiJuice desea cumplir con la demanda mínima de $d_k$ litros jugo del tipo $k\\in K$:" ] }, { "cell_type": "markdown", "id": "14439d0a", "metadata": {}, "source": [ "$$\n", " \\sum_{i\\in R} x_{ki} \\ge d_k,\\ \\forall k\\in K;\n", "$$" ] }, { "cell_type": "markdown", "id": "descending-testament", "metadata": {}, "source": [ "### Naturaleza de las Variables" ] }, { "cell_type": "markdown", "id": "a7946f1f", "metadata": {}, "source": [ "Solo pueden usarse cantidades positivas de cada fruta $i\\in R$ para el jugo $k\\in K$:" ] }, { "cell_type": "markdown", "id": "90fa50c3", "metadata": {}, "source": [ "$$\n", " x_{ki} \\ge 0,\\ \\forall k\\in K,i\\in R.\n", "$$" ] }, { "cell_type": "markdown", "id": "voluntary-couple", "metadata": {}, "source": [ "### Función objetivo" ] }, { "cell_type": "markdown", "id": "3094f9dd", "metadata": {}, "source": [ "Ingresos totales:" ] }, { "cell_type": "markdown", "id": "cbc1cd65", "metadata": {}, "source": [ "$$\n", " \\operatorname{máx}\\ \\sum_{k\\in K}\\sum_{i\\in R}p_{k}x_{ki}\n", "$$" ] }, { "cell_type": "markdown", "id": "geographic-header", "metadata": {}, "source": [ "## Implementación" ] }, { "cell_type": "markdown", "id": "219f43ce", "metadata": {}, "source": [ "**b.** Resuelve el modelo planteado utilizando la librería de PuLP en Python. ¿Cuál es la solución óptima del problema? " ] }, { "cell_type": "markdown", "id": "2a1a82c3", "metadata": {}, "source": [ "### Librerías" ] }, { "cell_type": "markdown", "id": "f597d592", "metadata": {}, "source": [ "Importa la librería `pulp` para crear y resolver el modelo." ] }, { "cell_type": "code", "execution_count": 2, "id": "323a0476", "metadata": {}, "outputs": [], "source": [ "import pulp as lp" ] }, { "cell_type": "markdown", "id": "837873b4", "metadata": {}, "source": [ "### Conjuntos" ] }, { "cell_type": "markdown", "id": "48fddac0", "metadata": {}, "source": [ "Define los conjuntos `K` y `R` que representan los jugos y las frutas respectivamente.\n", "\n", "Recuerda que por conveniencia de preservar el orden de los elementos de los conjuntos, no siempre deberás definirlos con el tipo `set`." ] }, { "cell_type": "code", "execution_count": 3, "id": "d9209bb7", "metadata": {}, "outputs": [], "source": [ "# Jugos\n", "K = [\"Saludable\", \"Tropical\", \"Mañanero\", \"Colombiano\", \"Refrescante\", \"Light\"]\n", "\n", "# Frutas\n", "R = [\"Piña\", \"Guayaba\", \"Níspero\", \"Zapote\"]" ] }, { "cell_type": "markdown", "id": "8c58ff99", "metadata": {}, "source": [ "### Parámetros" ] }, { "cell_type": "markdown", "id": "d981d80d", "metadata": {}, "source": [ "Define o importa los parámetros del modelo." ] }, { "cell_type": "code", "execution_count": 4, "id": "16df6fb4", "metadata": {}, "outputs": [], "source": [ "# Porcentaje mínimo de litros de la fruta i in R en el jugo k in K\n", "l = {\n", " (\"Saludable\", \"Piña\"): 0.32,\n", " (\"Saludable\", \"Guayaba\"): 0.27,\n", " (\"Saludable\", \"Níspero\"): 0.12,\n", " (\"Saludable\", \"Zapote\"): 0.13,\n", " (\"Tropical\", \"Piña\"): 0.18,\n", " (\"Tropical\", \"Guayaba\"): 0.20,\n", " (\"Tropical\", \"Níspero\"): 0.21,\n", " (\"Tropical\", \"Zapote\"): 0.11,\n", " (\"Mañanero\", \"Piña\"): 0.07,\n", " (\"Mañanero\", \"Guayaba\"): 0.31,\n", " (\"Mañanero\", \"Níspero\"): 0.28,\n", " (\"Mañanero\", \"Zapote\"): 0.22,\n", " (\"Colombiano\", \"Piña\"): 0.11,\n", " (\"Colombiano\", \"Guayaba\"): 0.05,\n", " (\"Colombiano\", \"Níspero\"): 0.15,\n", " (\"Colombiano\", \"Zapote\"): 0.18,\n", " (\"Refrescante\", \"Piña\"): 0.16,\n", " (\"Refrescante\", \"Guayaba\"): 0.29,\n", " (\"Refrescante\", \"Níspero\"): 0.02,\n", " (\"Refrescante\", \"Zapote\"): 0.23,\n", " (\"Light\", \"Piña\"): 0.26,\n", " (\"Light\", \"Guayaba\"): 0.10,\n", " (\"Light\", \"Níspero\"): 0.14,\n", " (\"Light\", \"Zapote\"): 0.30,\n", "}\n", "\n", "# Porcentaje máximo de litros de la fruta i in R en el jugo k in K\n", "u = {\n", " (\"Saludable\", \"Piña\"): 0.95,\n", " (\"Saludable\", \"Guayaba\"): 0.83,\n", " (\"Saludable\", \"Níspero\"): 0.66,\n", " (\"Saludable\", \"Zapote\"): 0.87,\n", " (\"Tropical\", \"Piña\"): 0.92,\n", " (\"Tropical\", \"Guayaba\"): 0.76,\n", " (\"Tropical\", \"Níspero\"): 0.69,\n", " (\"Tropical\", \"Zapote\"): 0.56,\n", " (\"Mañanero\", \"Piña\"): 0.81,\n", " (\"Mañanero\", \"Guayaba\"): 0.61,\n", " (\"Mañanero\", \"Níspero\"): 0.78,\n", " (\"Mañanero\", \"Zapote\"): 0.94,\n", " (\"Colombiano\", \"Piña\"): 0.82,\n", " (\"Colombiano\", \"Guayaba\"): 0.88,\n", " (\"Colombiano\", \"Níspero\"): 0.63,\n", " (\"Colombiano\", \"Zapote\"): 0.98,\n", " (\"Refrescante\", \"Piña\"): 0.60,\n", " (\"Refrescante\", \"Guayaba\"): 0.85,\n", " (\"Refrescante\", \"Níspero\"): 0.73,\n", " (\"Refrescante\", \"Zapote\"): 0.78,\n", " (\"Light\", \"Piña\"): 0.50,\n", " (\"Light\", \"Guayaba\"): 0.55,\n", " (\"Light\", \"Níspero\"): 0.82,\n", " (\"Light\", \"Zapote\"): 0.91,\n", "}\n", "\n", "# Litros disponibles de la fruta i in R\n", "b = {\n", " \"Piña\": 6318,\n", " \"Guayaba\": 4500,\n", " \"Níspero\": 4683,\n", " \"Zapote\": 2121,\n", "}\n", "\n", "# Demanda del jugo k in K\n", "d = {\n", " \"Saludable\": 1200,\n", " \"Tropical\": 925,\n", " \"Mañanero\": 1865,\n", " \"Colombiano\": 1035,\n", " \"Refrescante\": 2231,\n", " \"Light\": 1353,\n", "}\n", "\n", "# Precio del jugo k in K\n", "p = {\n", " \"Saludable\": 9000,\n", " \"Tropical\": 5000,\n", " \"Mañanero\": 6000,\n", " \"Colombiano\": 10000,\n", " \"Refrescante\": 7000,\n", " \"Light\": 8000,\n", "}" ] }, { "cell_type": "markdown", "id": "70fd6598", "metadata": {}, "source": [ "### Objeto del modelo" ] }, { "cell_type": "markdown", "id": "aa975e80", "metadata": {}, "source": [ "Construye un problema al que luego agregarás las restricciones y la función objetivo." ] }, { "cell_type": "code", "execution_count": 5, "id": "a1501b81", "metadata": {}, "outputs": [], "source": [ "problema = lp.LpProblem(name=\"optijuice\", sense=lp.LpMinimize)" ] }, { "cell_type": "markdown", "id": "970af788", "metadata": {}, "source": [ "### Variables de decisión" ] }, { "cell_type": "markdown", "id": "1e670ec8", "metadata": {}, "source": [ "Define las variables del problema de manera que estén contenidas en diccionarios indexados en los conjuntos de sus variables respectivas." ] }, { "cell_type": "code", "execution_count": 6, "id": "e1febe93", "metadata": {}, "outputs": [], "source": [ "# Litros de la fruta i in R para producir el jugo k in K\n", "x = {\n", " (k, i): lp.LpVariable(\n", " name=f\"litros_fruta_{i}_jugo_{k}\", lowBound=0, upBound=None, cat=lp.LpContinuous\n", " )\n", " for k in K\n", " for i in R\n", "}" ] }, { "cell_type": "markdown", "id": "f843462c", "metadata": {}, "source": [ "### Función objetivo" ] }, { "cell_type": "markdown", "id": "97df9059", "metadata": {}, "source": [ "Agrega al problema la función objetivo. Recuerda que al definir el problema, ya definiste si este es de maximización o minimización." ] }, { "cell_type": "code", "execution_count": 7, "id": "2fd8a365", "metadata": {}, "outputs": [], "source": [ "# Ingresos totales\n", "problema += sum(p[k] * x[k, i] for k in K for i in R), \"ingresos_totales\"" ] }, { "cell_type": "markdown", "id": "89f524db", "metadata": {}, "source": [ "### Restricciones" ] }, { "cell_type": "markdown", "id": "77e7e409", "metadata": {}, "source": [ "Agrega al problema las restricciones del modelo." ] }, { "cell_type": "code", "execution_count": 8, "id": "f986d5ee", "metadata": {}, "outputs": [], "source": [ "# Se garantiza el mínimo de fruta i in R en el jugo k in K\n", "for k in K:\n", " for i in R:\n", " problema += (\n", " x[k, i] >= l[k, i] * sum(x[k, j] for j in R),\n", " f\"minimo_fruta_{i}_jugo_{k}\",\n", " )\n", "\n", "# Se garantiza el máximo de fruta i in R en el jugo k in K \n", "for k in K:\n", " for i in R:\n", " problema += (\n", " x[k, i] <= u[k, i] * sum(x[k, j] for j in R),\n", " f\"maximo_fruta_{i}_jugo_{k}\",\n", " )\n", "\n", "# Se garantiza que no se utilice más fruta de la que hay disponible\n", "for i in R:\n", " problema += (\n", " sum(x[k, i] for k in K) <= b[i],\n", " f\"límite_fruta_{i}\",\n", " )\n", "\n", "# Se satisface la demanda\n", "for k in K:\n", " problema += (\n", " sum(x[k, i] for i in R) >= d[k],\n", " f\"demanda_mínima_jugo_{k}\",\n", " )" ] }, { "cell_type": "markdown", "id": "265a2a10", "metadata": {}, "source": [ "### Resolver el problema" ] }, { "cell_type": "markdown", "id": "d7661201", "metadata": {}, "source": [ "Invoca el optimizador. Este paso le asigna un valor a las variables incluidas en las restricciones o función objetivo del modelo." ] }, { "cell_type": "code", "execution_count": 9, "id": "ae811704", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Welcome to the CBC MILP Solver \n", "Version: 2.10.8 \n", "Build Date: May 6 2022 \n", "\n", "command line - cbc /tmp/298c84e534c64fcc9eaf19c759eae998-pulp.mps timeMode elapsed branch printingOptions all solution /tmp/298c84e534c64fcc9eaf19c759eae998-pulp.sol (default strategy 1)\n", "At line 2 NAME MODEL\n", "At line 3 ROWS\n", "At line 63 COLUMNS\n", "At line 328 RHS\n", "At line 387 BOUNDS\n", "At line 388 ENDATA\n", "Problem MODEL has 58 rows, 24 columns and 240 elements\n", "Coin0008I MODEL read with 0 errors\n", "Option for timeMode changed from cpu to elapsed\n", "Presolve 58 (0) rows, 24 (0) columns and 240 (0) elements\n", "Perturbing problem by 0.001% of 20534.118 - largest nonzero change 0.072968449 ( 0.0011611913%) - largest zero change 0\n", "0 Obj 0 Primal inf 8439.9001 (6)\n", "28 Obj 63406111\n", "Optimal - objective value 63406000\n", "Optimal objective 63406000 - 28 iterations time 0.002\n", "Option for printingOptions changed from normal to all\n", "Total time (CPU seconds): 0.00 (Wallclock seconds): 0.00\n", "\n" ] }, { "data": { "text/plain": [ "1" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "problema.solve()" ] }, { "cell_type": "markdown", "id": "655b238a", "metadata": {}, "source": [ "### Imprimir resultados" ] }, { "cell_type": "markdown", "id": "8a7a8a35", "metadata": {}, "source": [ "Antes de estudiar el óptimo del modelo, identifica en el estado del optimizador si pudo resolver el problema." ] }, { "cell_type": "code", "execution_count": 10, "id": "whole-trust", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Estado del optimizador: Optimal'" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f\"Estado del optimizador: {lp.LpStatus[problema.status]}\"" ] }, { "cell_type": "markdown", "id": "ea6fe01e", "metadata": {}, "source": [ "Identifica también el valor de la función objetivo." ] }, { "cell_type": "code", "execution_count": 11, "id": "11b75d2c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Ingresos totales: 63406000.0'" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f\"Ingresos totales: {lp.value(problema.objective)}\"" ] }, { "cell_type": "markdown", "id": "6e59d608", "metadata": {}, "source": [ "Por último, imprime de manera estructurada el valor de las variables de decisión y otras expresiones de interés." ] }, { "cell_type": "code", "execution_count": 16, "id": "26a9eb28", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\tPiña\tGuayaba\tNíspero\tZapote\n", "Saludable\t 576.00\t 324.00\t 144.00\t 156.00\t\n", "Tropical\t 444.00\t 185.00\t 194.25\t 101.75\t\n", "Mañanero\t 130.55\t 801.95\t 522.20\t 410.30\t\n", "Colombiano\t 113.85\t 231.98\t 155.25\t 533.92\t\n", "Refrescante\t 356.96\t 1316.29\t 44.62\t 513.13\t\n", "Light\t 622.38\t 135.30\t 189.42\t 405.90\t\n" ] } ], "source": [ "for i in R:\n", " print(f\"\\t{i}\", end=\"\")\n", "print()\n", "\n", "for k in K:\n", " print(k, end=\"\\t\")\n", " for i in R:\n", " print(f\"{lp.value(x[k, i]): .2f}\", end=\"\\t\",\n", " )\n", " print()" ] }, { "cell_type": "markdown", "id": "4a7dbe6d", "metadata": {}, "source": [ "## Créditos" ] }, { "cell_type": "markdown", "id": "hired-insulation", "metadata": {}, "source": [ "Equipo Principios de Optimización
\n", "Autores: Juan Felipe Rengifo
\n", "Desarrollo: Juan Felipe Rengifo, Alejandro Mantilla
\n", "Última fecha de modificación: 07/04/2023" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.0" } }, "nbformat": 4, "nbformat_minor": 5 }